
package UI;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import model.CPU;
import model.IODevice;
import model.SystemTimer;

/**
 * 
 * @author Sydney Lin UI extends JFrame and contains InputPanel and OutputPanel.
 * @version 1.0
 */
@SuppressWarnings("serial")
public class UI extends JFrame
{
  /**
   * The panel width.
   */
  public static final int WIDTH = 650;

  /**
   * The panel height.
   */
  public static final int HEIGHT = 600;
  
  /**
   * The default number of steps to run this simulation.
   */
  public static final int DEFAULT_RUNTIME = 1000000;
  
  /**
   * The CPU.
   */
  private CPU my_cpu;
  
  /**
   * The input panel.
   */
  private InputPanel my_input_panel;
  
  /**
   * The output panel.
   */
  private OutputPanel my_output_panel;
  
  /**
   * The list panel.
   */
  private ListPanel my_list_panel;
  
  /**
   * The text field to enter the run time.
   */
  private JTextField my_run_time;
  
  /**
   * The text that can interrupt the CPU.
   */
  private JTextField my_interrupt_text;

  /**
   * UI constructor.
   * @param the_cpu The CPU.
   */
  public UI(final CPU the_cpu)
  {
    super();
    my_cpu = the_cpu;    
    my_run_time = new JTextField(10);
    my_run_time.setText(Integer.toString(DEFAULT_RUNTIME));
    my_input_panel = new InputPanel();
    my_output_panel = new OutputPanel();
    my_cpu.addObserver(my_output_panel);
    my_interrupt_text = new JTextField(30);
    my_interrupt_text.addActionListener(new InterruptTextListener());
    final JPanel the_layout_panel = new JPanel();
    final JPanel the_run_time_panel = new JPanel();
    final JPanel the_text_panel = new JPanel();
    final JButton the_run_button = new JButton("Run");
    final JButton the_stop_button = new JButton("Stop");
    the_run_button.addActionListener(new RunButtonListener());
    the_stop_button.addActionListener(new StopButtonListener());
    add(the_layout_panel);
    the_layout_panel.add(my_input_panel, BorderLayout.CENTER);
    the_layout_panel.add(the_run_time_panel);
    the_run_time_panel.add(new JLabel("Running time"));
    the_run_time_panel.add(my_run_time);
    the_run_time_panel.add(the_run_button);
    the_run_time_panel.add(the_stop_button);
    the_layout_panel.add(the_text_panel);
    the_text_panel.add(new JLabel("Type to interrupt the CPU"));
    the_text_panel.add(my_interrupt_text);
    the_layout_panel.add(my_output_panel, BorderLayout.CENTER);
    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    setTitle("Scheduler Simulator");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    pack();
  }
  
  /**
   * The listener for the "Run" button. 
   * @author DoubleS
   * @version 1.0
   */
  private class RunButtonListener implements ActionListener
  {
    @Override
    public void actionPerformed(final ActionEvent the_event)
    {
      //Test the input: print the input to the output panel.
      /**
      my_output_panel.appendText("\nRun time is: " + my_run_time.getText().toString() + "\n");
      final ListPanel a_list_panel = my_input_panel.getListPanel();
      
      final DefaultListModel a_process_list = a_list_panel.getProcessList();
      for (Object o : a_process_list.toArray())
      {
        ((OutputPanel) my_output_panel).appendText(o.toString() + "\n");
      }*/
      
      my_output_panel.clear();
      my_output_panel.appendText("Report: \n\n");
      final int a_max_counter = Integer.parseInt(my_run_time.getText());
      final ListPanel a_list_panel = my_input_panel.getListPanel();
      final DefaultListModel a_process_list = a_list_panel.getProcessList();
      my_cpu.reset();
      my_cpu.setupSimulation(a_max_counter, a_process_list);
      
      final SystemTimer timer = my_cpu.getTimer();
      final IODevice io_1 = my_cpu.getIODevices()[0];
      final IODevice io_2 = my_cpu.getIODevices()[1];
      
      final ExecutorService simulator = Executors.newCachedThreadPool();
      simulator.execute(my_cpu);
      simulator.execute(io_1);
      simulator.execute(io_2);
      simulator.execute(timer);
      simulator.shutdown();      
    }    
  }
  private class StopButtonListener implements ActionListener
  {
    @Override
    public void actionPerformed(final ActionEvent the_event)
    {
      
      my_cpu.stop();
  
    }    
  }
  
  /**
   * Listener for interrupt text.
   * 
   * @author DoubleS
   * @version 1.0
   */
  private class InterruptTextListener implements ActionListener
  {
    @Override
    public void actionPerformed(final ActionEvent the_even)
    {
      my_cpu.keyboardInterrupt();
    }    
  }
}
